package com.pubinfo.passbook.common.service.contract.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pubinfo.passbook.common.entity.TContractBase;
import com.pubinfo.passbook.common.entity.TContractPerformance;
import com.pubinfo.passbook.common.entity.TContractProject;
import com.pubinfo.passbook.common.enums.ContractStatusEnum;
import com.pubinfo.passbook.common.exception.ServiceException;
import com.pubinfo.passbook.common.mapper.TContractBaseMapper;
import com.pubinfo.passbook.common.mapper.TContractWbsProjectMapper;
import com.pubinfo.passbook.common.mapper.TRabbitmqPersonMapper;
import com.pubinfo.passbook.common.model.constant.RoleEnum;
import com.pubinfo.passbook.common.model.dto.contract.*;
import com.pubinfo.passbook.common.model.vo.base.BusinessErrorCode;
import com.pubinfo.passbook.common.model.vo.base.JsonResult;
import com.pubinfo.passbook.common.model.vo.base.MyPage;
import com.pubinfo.passbook.common.model.vo.base.ResultCode;
import com.pubinfo.passbook.common.model.vo.contract.ContractBaseExcel;
import com.pubinfo.passbook.common.model.vo.contract.ContractDetailInfoVo;
import com.pubinfo.passbook.common.model.vo.contract.ContractDetailVo;
import com.pubinfo.passbook.common.service.contract.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author admin
 * @description 针对表【t_contract_base(合同基础信息表)】的数据库操作Service实现
 * @createDate 2021-12-03 10:39:59
 */
@Slf4j
@Service
public class TContractBaseServiceImpl extends ServiceImpl<TContractBaseMapper, TContractBase> implements TContractBaseService {
  @Resource
  TRabbitmqPersonMapper personMapper;
  @Resource
  private TContractInvoiceApplyService contractInvoiceApplyService;
  
  @Resource
  private TContractInvoiceHeaderService contractInvoiceHeaderService;
  
  @Resource
  private TContractWbsProjectMapper wbsProjectMapper;
  @Resource
  private TContractProjectService contractProjectService;
    
    @Resource
    private TContractPerformanceService contractPerformanceService;
    
    @Resource
    private TContractPaymentHeaderService contractPaymentHeaderService;
    
    @Resource
    private TContractWriteoffHeaderService contractWriteoffHeaderService;

    @Override
    public TContractBase getContractById(Integer id) {
        TContractBase contract = this.baseMapper.selectById(id);

        if (Objects.isNull(contract))
            throw new ServiceException(BusinessErrorCode.CONTRACT_NOT_FUND);

        return contract;
    }
    
    @Override
    public MyPage<TContractBase> selectContractList(ContractListParam contractListParam) {
        //根据不同用户权限，查询列表
        /**
         * 1、系统管理员：除mdm,4a数据不能编辑外，可以操作、查看所有页面。 contract_admin
         * 2、单位负责人、部门领导：可查看所有页面，可查询本人所属单位及下属单位所有单据和报表数据。
         * 3、合同认领(执行)人：可查看本人所属单位相关的未认领合同以及本人已认领、执行中、执行完成、已关闭的合同。
         * 4、财务人员：可查看本人所属单位及下属单位所有单据和报表数据，不能认领和执行合同。
         * 市公司管理员能看到市内所有单据，省公司管理员能看到全省
         */
        
        MyPage<TContractBase> iPage = contractListParam.getMyPage();
        return this.baseMapper.selectContractList(iPage, contractListParam);
    }

    /**
     * 查询合同信息
     */
    @Override
    public ContractDetailInfoVo contractInfo(ContractIdParam param) {
        return baseMapper.getContractDetailInfo(param.getContractId());
    }

    @Override
    public ContractDetailVo contractDetail(ContractIdParam param) {

        ContractDetailVo detail = new ContractDetailVo();
        //合同信息
        ContractDetailInfoVo contract = baseMapper.getContractDetailInfo(param.getContractId());
        if (Objects.isNull(contract))
            throw new ServiceException(BusinessErrorCode.CONTRACT_NOT_FUND);
        detail.setContract(contract);

        //已开发票信息
        detail.setInvoices(contractInvoiceHeaderService.getContractInvoice(param.getContractId()));

        //税金计提明细
        detail.setContractWriteOffVos(contractWriteoffHeaderService.getContractWriteOffList(param.getContractId()));
    
        //收款计划
        QueryWrapper<TContractPerformance> qw = new QueryWrapper<>();
        qw.lambda().eq(TContractPerformance::getContractId, param.getContractId());
        detail.setPerformances(contractPerformanceService.list(qw));
    
        //已收款明细
        detail.setPaymentLists(contractPaymentHeaderService.getPaymentItems(param.getContractId()));
    
        //相关单据 申请单和报账单
        detail.setContractRelateDocs(contractInvoiceApplyService.getContractRelateDoc(param.getContractId()));
        detail.setWbsProjects(wbsProjectMapper.findContractWbsProjectByContractId(contract.getContractId()));
//        contractProjectService.lambdaQuery().eq(TContractProject::getContractId,contract.getContractId())
        return detail;
    }
    
    @Override
    @Transactional
    public JsonResult<ResultCode> contractAdopt(String acct, ContractAdoptParam param) {
        TContractBase contract = getContractById(param.getContractId());

//        if (contract.getStatus() != ContractStatusEnum.NO_CLAIM.getStatus())
//            throw new ServiceException(BusinessErrorCode.CONTRACT_CANT_CLAIM);
//
        //不强控
//        if (Objects.isNull(param.getWbsProjects()) || param.getWbsProjects().isEmpty())
//            throw new ServiceException(BusinessErrorCode.WBS_LESS_ONE);
//
        //财务没有权限认领
    
        if (RoleEnum.CONTRACT_FINANCE.roleCode.equals(param.getRoleCode())) {
            throw new ServiceException(ResultCode.FORBIDDEN);
        }
        contract.setModifiedBy(acct);
      contract.setStatus(ContractStatusEnum.CLAIMED.getStatus());
      contract.setProcessUser(acct);//认领人
      contract.setProcessName(personMapper.selectAcctNameByAcct(acct));
      contract.setProcessTime(new Date());//认领时间
        contract.setStatus(ContractStatusEnum.CLAIMED.getStatus());//状态
        contract.setAttachment(param.getAttachment());//附件地址
        contract.setApprovedAmount(param.getApprovedAmount()).setOffsetAmount(param.getOffsetAmount());
      contract.setResidualWriteOff(param.getResidualWriteOff());
      contract.setCollectedAmount(param.getCollectedAmount());
      contract.setInvoiceAmount(param.getInvoiceAmount());
        this.baseMapper.updateById(contract);
        //保存收款计划
        if (Objects.nonNull(param.getPerformances())) {
            for (TContractPerformance performance : param.getPerformances()) {
                performance.setContractId(param.getContractId());
                contractPerformanceService.save(performance);
            }
        }
    
        //先删除已有关系，再重建。
        contractProjectService.lambdaUpdate().eq(TContractProject::getContractId, contract.getContractId()).remove();
        //保存成本开支
        contractProjectService.saveBatch(TContractProject.toList(param.getWbsProjects(), contract.getContractId()));
        return JsonResult.success(ResultCode.SUCCESS);
    }
  @Override
  public JsonResult<ResultCode> cancelAdopt(String acct, ContractIdParam param) {
    TContractBase contract = getContractById(param.getContractId());
    contract.setStatus(ContractStatusEnum.NO_CLAIM.getStatus());
    contract.setModifiedBy(acct);
    this.baseMapper.updateById(contract);
    
    return JsonResult.success(ResultCode.SUCCESS);
  }
  
  @Override
  public Boolean contractAdopt(String acct, String contractCode) {
    TContractBase contract = lambdaQuery().eq(TContractBase::getContractCode, contractCode).one();
  
    contract.setProcessUser(acct);//认领人
  
    contract.setProcessName(personMapper.selectAcctNameByAcct(acct));
    contract.setModifiedBy(acct);
    contract.setProcessTime(new Date());//认领时间
    contract.setStatus(ContractStatusEnum.CLAIMED.getStatus());//状态
    this.baseMapper.updateById(contract);
    return true;
  }
  
  @Override
  public List<ContractBaseExcel> listByStatus(ContractStatusEnum status) {
    
    return this.baseMapper.listByStatus(status.getStatus());
  }
  
  @Override
  public JsonResult<ResultCode> contractClose(String acct, ContractIdParam param) {
    
    TContractBase contract = getContractById(param.getContractId());
//
//        if (ContractStatusEnum.CLOSE == ContractStatusEnum.getEnum(contract.getStatus()))
//            throw new ServiceException(BusinessErrorCode.CONTRACT_CLOSED);
    contract.setModifiedBy(acct);
    
    if (!contract.getStatus().equals(ContractStatusEnum.CLOSE.getStatus())) {
    
        contract.setStatus(ContractStatusEnum.CLOSE.getStatus());
      } else {
    
        contract.setStatus(ContractStatusEnum.NO_CLAIM.getStatus());
      }
  
      //contract.setProcessUser(acct);//关闭人
      baseMapper.updateById(contract);
        
        return JsonResult.success(ResultCode.SUCCESS);
    }

    /**
     * 更改可开票金额
     *
     * @param contractId
     * @param amount
     */
    @Override
    public boolean modifyInvoiceAmount(Integer contractId, BigDecimal amount) {
      return this.baseMapper.modifyInvoiceAmount(contractId, amount) == 1;
    }
  
  /**
   * 已认领合同情况查询
   */
  @Override
  public MyPage<ClaimedList> getContractClaimedList(ContractTrialParam param) {
    MyPage<ClaimedList> iPage = param.getMyPage();
    return this.baseMapper.getContractClaimedList(iPage, param);
  }

    /**
     * 下载excel
     */
    @Override
    public List<ClaimedList> getContractDownloadExcal(ContractTrialParam param) {
      return this.baseMapper.getContractClaimedList(param);
    }
  
  /**
     * 合同清洗结果查询
     */
    @Override
    public MyPage<ContractClearResultList> selectContractClearResultList(ContractClaerParam param) {
      MyPage<ContractClaerParam> iPage = param.getMyPage();
      MyPage<ContractClearResultList> listMyPage = this.baseMapper.getContractClearResultList(iPage, param);
      return listMyPage;
    }

    @Override
    public List<ContractClearResultList> getContractClearResulDownloadExcal(ContractClaerParam param) {
        return this.baseMapper.getContractClearResultList(param);
    }
}
